<template>
  <div class="websocket-monitor">
    <div class="threads-container">
      <div class="section-title">线程状态</div>
      <div class="thread-list">
        <div v-for="thread in threads" :key="`thread-${thread.id}`" class="thread-item">
          <div class="thread-icon" :class="{ 'thread-active': thread.active }">
            <i class="thread-status"></i>
          </div>
          <div class="thread-content">
            <span class="thread-title">Thread {{ thread.id }}: {{ thread.type }}</span>
            <span class="thread-info">{{ thread.info }}</span>
          </div>
        </div>
      </div>
    </div>

    <div class="charts-container">
      <div class="chart">
        <h3>电磁特性</h3>
        <div ref="voltageChartRef" class="chart-container"></div>
      </div>
      <div class="chart">
        <h3>a相电子电压</h3>
        <div ref="phaseChartRef" class="chart-container"></div>
      </div>
    </div>

    <div class="system-info">
      <div class="section-title">系统信息</div>
      <div class="info-list">
        <div v-for="(info, key) in systemInfo" :key="key" class="info-item">
          <span class="info-label">{{ getInfoLabel(key) }}:</span>
          <span class="info-value">{{ info }}</span>
        </div>
      </div>
    </div>

    <div v-if="completed" class="completion-notice">
      <el-alert :closable="false" show-icon title="运行完成" type="success"/>
    </div>

    <div v-if="socketError" class="socket-error">
      <el-alert :closable="false" show-icon title="WebSocket连接错误" type="error"/>
    </div>
  </div>
</template>

<script lang="ts" setup>
import * as Plotly from 'plotly.js-dist-min'
import { onMounted, onUnmounted, ref, watch } from 'vue'

// Define props to receive data from parent
const props = defineProps({
  chartData: {
    type: Object,
    default: () => ({
      voltageData: [],
      phaseData: [],
      timeData: [],
    }),
  },
  threadsData: {
    type: Array as () => {
      id: number
      type: string
      info?: string
      active: boolean
    }[],
    default: () => [],
  },
  systemInfoData: {
    type: Object,
    default: () => ({
      electricalNodes: 10,
      controlNodes: 69,
      runTime: 'Nov 12, 2024, 16:37:27',
    }),
  },
  isCompleted: {
    type: Boolean,
    default: false,
  },
  websocketUrl: {
    type: String,
    default: 'ws://localhost:8001/monitor',
  },
})

// Chart refs
const voltageChartRef = ref<HTMLElement | null>(null)
const phaseChartRef = ref<HTMLElement | null>(null)
let voltageChart: any = null
let phaseChart: any = null

// WebSocket connection
let socket: WebSocket | null = null
const socketError = ref(false)

// Data models with default values
const threads = ref([
  { id: 0, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 1, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 2, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 3, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 4, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 5, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 6, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 7, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 8, type: 'Node', info: 'component (newGraph) will be chosen as loop node with initial value 0', active: true },
  { id: 9, type: 'using config_referring=0', active: false },
])

const systemInfo = ref({
  electricalNodes: 10,
  controlNodes: 69,
  runTime: 'Nov 12, 2024, 16:37:27',
})

const completed = ref(props.isCompleted)

// Helper function to get human-readable labels for system info
const getInfoLabel = (key: string): string => {
  const labels: Record<string, string> = {
    electricalNodes: '电气系统节点数',
    controlNodes: '电气和控制系统节点数',
    runTime: '程序运行时间',
  }
  return labels[key] || key
}

// WebSocket connection setup
const initWebSocket = () => {
  // Close existing connection if any
  if (socket) {
    socket.close()
  }

  socketError.value = false

  try {
    socket = new WebSocket(props.websocketUrl)

    socket.addEventListener('open', () => {
      console.log('WebSocket connection established')
      // Request initial data if needed
      sendMessage({ type: 'init', action: 'requestData' })
    })

    socket.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data)
        processWebSocketData(data)
      } catch (error) {
        console.error('Error parsing WebSocket message:', error)
      }
    }

    socket.onerror = (err) => {
      console.error('WebSocket error:', err)
      // socketError.value = true
    }

    socket.addEventListener('close', () => {
      console.log('WebSocket connection closed')
      // Try to reconnect after a delay
      setTimeout(() => {
        if (!socket || socket.readyState === WebSocket.CLOSED) {
          initWebSocket()
        }
      }, 5000)
    })
  } catch (error) {
    console.error('Failed to establish WebSocket connection:', error)
    socketError.value = true
  }
}

// Process incoming WebSocket data
const processWebSocketData = (data: any) => {
  if (!data || typeof data !== 'object') return

  // Update threads data
  if (data.threads && Array.isArray(data.threads)) {
    threads.value = data.threads
  }

  // Update system info
  if (data.systemInfo && typeof data.systemInfo === 'object') {
    systemInfo.value = { ...systemInfo.value, ...data.systemInfo }
  }

  // Update chart data
  if (data.chartData) {
    const { voltageData, phaseData, timeData } = data.chartData
    updateCharts(voltageData, phaseData, timeData)
  }

  // Update completion status
  if (typeof data.completed === 'boolean') {
    completed.value = data.completed
  }
}

// Send message to server
const sendMessage = (data: any) => {
  if (socket && socket.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify(data))
  }
}

// Remove sequential loading functions and refs
const loadThreadsSequentially = () => {
  threads.value = props.threadsData || threads.value
}

const loadSystemInfoSequentially = () => {
  systemInfo.value = (props.systemInfoData as typeof systemInfo.value) || systemInfo.value
}

// Watch for changes in props
watch(
  () => props.threadsData,
  (newData) => {
    if (newData && newData.length > 0) {
      threads.value = newData as typeof threads.value
      loadThreadsSequentially()
    }
  },
  { deep: true, immediate: true }
)

watch(
  () => props.systemInfoData,
  (newData) => {
    if (newData) {
      systemInfo.value = { ...systemInfo.value, ...newData }
      loadSystemInfoSequentially()
    }
  },
  { deep: true, immediate: true }
)

watch(
  () => props.chartData,
  (newData) => {
    if (newData) {
      updateCharts(newData.voltageData, newData.phaseData, newData.timeData)
    }
  },
  { deep: true }
)

watch(
  () => props.isCompleted,
  (newValue) => {
    completed.value = newValue
  }
)

watch(
  () => props.websocketUrl,
  () => {
    // Reinitialize WebSocket when URL changes
    initWebSocket()
  }
)

// Initialize Plotly charts
const initCharts = () => {
  if (voltageChartRef.value && phaseChartRef.value) {
    // Generate initial data if not provided
    const initialData = generateMockData()

    // Create voltage chart
    Plotly.newPlot(
      voltageChartRef.value,
      [
        {
          x: initialData.timeData,
          y: initialData.voltageData,
          type: 'scatter',
          mode: 'lines',
          name: 'Ts_0',
          line: {
            color: '#1890ff',
            width: 1.5,
          },
        },
      ],
      {
        margin: { l: 50, r: 20, t: 30, b: 30 },
        xaxis: {
          title: '时间(s)',
          range: [0, 3],
        },
        yaxis: {
          title: '电压(V)',
        },
        autosize: true,
      },
      {
        responsive: true,
      }
    )

    // Create phase chart
    Plotly.newPlot(
      phaseChartRef.value,
      [
        {
          x: initialData.timeData,
          y: initialData.phaseData,
          type: 'scatter',
          mode: 'lines',
          name: 'a相',
          line: {
            color: '#1890ff',
            width: 1.5,
          },
        },
      ],
      {
        margin: { l: 50, r: 20, t: 30, b: 30 },
        xaxis: {
          title: '时间(s)',
          range: [0, 3],
        },
        yaxis: {
          title: '电压(V)',
        },
        autosize: true,
      },
      {
        responsive: true,
      }
    )

    // Store chart instances
    voltageChart = voltageChartRef.value
    phaseChart = phaseChartRef.value

    // Handle window resize
    window.addEventListener('resize', () => {
      if (voltageChart && phaseChart) {
        Plotly.relayout(voltageChart, {
          'xaxis.autorange': true,
          'yaxis.autorange': true,
        })

        Plotly.relayout(phaseChart, {
          'xaxis.autorange': true,
          'yaxis.autorange': true,
        })
      }
    })
  }
}

// Generate mock data for charts
const generateMockData = () => {
  // Voltage chart data
  const voltageData: number[] = []
  const timeData: number[] = []
  const phaseData: number[] = []

  for (let i = 0; i < 300; i++) {
    const time = i * 0.01
    timeData.push(time)

    if (i < 50) {
      voltageData.push(180 + Math.random() * 20)
    } else if (i < 150) {
      voltageData.push(80 + Math.random() * 20)
    } else if (i < 200) {
      voltageData.push(140 + Math.random() * 20)
    } else {
      voltageData.push(90 + Math.random() * 20)
    }

    // Phase chart data
    phaseData.push(150 * Math.sin(10 * time))
  }

  return {
    voltageData,
    phaseData,
    timeData,
  }
}

// Update chart with new data
const updateCharts = (voltageData?: number[], phaseData?: number[], timeData?: number[]) => {
  if (!voltageData || !phaseData) {
    // If no data provided, use mock data
    const mockData = generateMockData()
    voltageData = mockData.voltageData
    phaseData = mockData.phaseData
    timeData = mockData.timeData
  }

  if (voltageChart) {
    Plotly.react(
      voltageChart,
      [
        {
          x: timeData,
          y: voltageData,
          type: 'scatter',
          mode: 'lines',
          name: 'Ts_0',
          line: {
            color: '#1890ff',
            width: 1.5,
          },
        },
      ],
      {
        margin: { l: 50, r: 20, t: 30, b: 30 },
        xaxis: {
          title: '时间(s)',
          range: [0, 3],
        },
        yaxis: {
          title: '电压(V)',
        },
        autosize: true,
      },
      {
        responsive: true,
      }
    )
  }

  if (phaseChart) {
    Plotly.react(
      phaseChart,
      [
        {
          x: timeData,
          y: phaseData,
          type: 'scatter',
          mode: 'lines',
          name: 'a相',
          line: {
            color: '#1890ff',
            width: 1.5,
          },
        },
      ],
      {
        margin: { l: 50, r: 20, t: 30, b: 30 },
        xaxis: {
          title: '时间(s)',
          range: [0, 3],
        },
        yaxis: {
          title: '电压(V)',
        },
        autosize: true,
      },
      {
        responsive: true,
      }
    )
  }
}

onMounted(() => {
  initCharts()
  initWebSocket()
  loadThreadsSequentially()
  loadSystemInfoSequentially()
})

onUnmounted(() => {
  // Clean up charts to prevent memory leaks
  if (voltageChart) {
    Plotly.purge(voltageChart)
    voltageChart = null
  }

  if (phaseChart) {
    Plotly.purge(phaseChart)
    phaseChart = null
  }

  // Close WebSocket connection
  if (socket) {
    socket.close()
    socket = null
  }
})

// Expose for parent component
defineExpose({
  updateCharts,
  sendMessage,
})
</script>

<style lang="scss" scoped>
.websocket-monitor {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 16px;
  overflow-y: auto;
  animation: fadeIn 0.3s ease;

  .section-title {
    margin-bottom: 10px;
    font-size: 16px;
    font-weight: 500;
  }

  .threads-container {
    padding: 12px;
    background-color: #fff;
    border-radius: 4px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);

    .thread-list {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    .thread-item {
      display: flex;
      align-items: center;
      padding: 8px;
      background-color: #fafafa;
      border-radius: 4px;

      .thread-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        margin-right: 12px;

        .thread-status {
          display: inline-block;
          width: 10px;
          height: 10px;
          background-color: #d9d9d9;
          border-radius: 50%;
        }

        &.thread-active .thread-status {
          background-color: #ff9800;
        }
      }

      .thread-content {
        display: flex;
        flex: 1;
        flex-direction: column;

        .thread-title {
          margin-bottom: 4px;
          font-weight: 500;
        }

        .thread-info {
          font-size: 12px;
          color: #666;
        }
      }
    }
  }

  .charts-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
    margin-bottom: 20px;

    .chart {
      padding: 12px;
      background-color: #fff;
      border-radius: 4px;
      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);

      h3 {
        margin: 0 0 12px 0;
        font-size: 14px;
        font-weight: 500;
        text-align: center;
      }

      .chart-container {
        width: 100%;
        height: 200px;
      }
    }
  }

  .system-info {
    padding: 12px;
    background-color: #fff;
    border-radius: 4px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);

    .info-list {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    .info-item {
      display: flex;
      margin-bottom: 8px;

      .info-label {
        min-width: 160px;
        margin-right: 8px;
        font-weight: 500;
      }

      .info-value {
        color: #333;
      }
    }
  }

  .completion-notice,
  .socket-error {
    margin-top: 12px;
  }
}

// Simplified animation for the whole container
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
</style>
